home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / keyb / kbuf11.zip / KBUF.ASM < prev    next >
Assembly Source File  |  1988-11-19  |  11KB  |  454 lines

  1.  title KBUF -- extend keyboard buffer
  2.  
  3. comment #
  4.  
  5. KBUF version 1.1  Copyright (C) 1988  Mark Adler
  6. All rights reserved.
  7.  
  8. Version history -
  9.  
  10. 1.0     26 May 1988     First public version
  11. 1.1     18 Nov 1988     Added queue stuff call (AH=0FFh)
  12.  
  13. kbuf.com -
  14.  
  15.  kbuf maintains a 127 entry (vs. 15 entry) typeahead buffer.  Also the
  16.  original 15 character buffer is retained so a maximum of 142 characters
  17.  are buffered.
  18.  
  19.  The following assumptions are made about the behavior of the keyboard
  20.  scan and support interrupts:
  21.  
  22.  1. The shift status is a byte stored at location 0:417h.
  23.  
  24.  2. The support routine is not re-entrant.
  25.  
  26.  kbuf also adds a new function to interrupt 16h---if AH is 0FFh, then
  27.  the scan code in DX is put into the queue, behind what is already
  28.  there (i.e., as if it were just typed).  This is different from
  29.  stacking, which puts the keystroke at the front of the queue.  On
  30.  return, AL=0 indicates success, AL=1 indicates failure (no room in
  31.  queue).
  32.  
  33. #
  34.  
  35.  
  36.  
  37. ;
  38. ; Interrupt vector segment definitions.
  39. ;
  40.  
  41. ints segment at 0
  42.  org 4*8h               ;Timer interrupt.
  43. int8 label word
  44.  org 4*9h               ;Scan interrupt.
  45. int9 label word
  46.  org 4*16h              ;Keyboard BIOS interrupt.
  47. int16 label word
  48.  org 417h
  49. KB_FLAG db ?            ;Keyboard shift status.
  50. ints ends
  51.  
  52.  
  53.  
  54. ;
  55. ; Program segment.
  56. ;
  57.  
  58. kbuf segment
  59.  assume CS:kbuf,DS:kbuf,ES:kbuf,SS:kbuf
  60.  
  61.  
  62.  
  63. ;
  64. ; Put data as low as DOS will allow.
  65.  org 5Ch
  66.  
  67. oldtv label dword
  68. oldt dw ?,?             ;Old timer routine address.
  69. oldsv label dword
  70. olds dw ?,?             ;Old keyboard scan routine address.
  71. oldkv label dword
  72. oldk dw ?,?             ;Old keyboard service routine address.
  73.  
  74. ink db ?,?              ;In kcopy--don't call it again.
  75.  
  76. kqs dw ?                ;Queue size in bytes.
  77. kqf dw ?                ;Queue front.
  78. kqr dw ?                ;Queue rear.
  79. kq label word           ;Queue.
  80. kqsz equ 128            ;Queue size in entries plus one.
  81.  
  82.  
  83.  
  84. ;
  85. ; Start of .COM code - jump to installation.
  86.  org 100h
  87. start:
  88.   jmp install
  89.  
  90.   db 13,'KBUF version 1.1  Copyright (C) 1988  Mark Adler',13,10
  91.   db 'All rights reserved.',13,10,'Z'-64
  92.  
  93.   org kq+kqsz*2         ;Start at end of queue.
  94.  
  95.  
  96.  
  97. ;
  98. ; Traps and their subroutines -
  99.  
  100.  assume CS:kbuf,SS:nothing      ;For all traps and subroutines.
  101.  
  102.  
  103.  
  104. timer proc near
  105.  
  106.   assume DS:nothing,ES:nothing
  107.  
  108.         ; save registers.
  109.   push AX
  110.   push BX
  111.   push DI
  112.   push DS
  113.   push ES
  114.  
  115.         ; enqueue keyboard data.
  116.   call kcopy
  117.   assume DS:kbuf,ES:kbuf
  118.  
  119.         ; restore registers and drop to next guy in chain.
  120.   pop ES
  121.   pop DS
  122.   assume DS:nothing,ES:nothing
  123.   pop DI
  124.   pop BX
  125.   pop AX
  126.   jmp oldtv
  127.  
  128. timer endp
  129.  
  130.  
  131.  
  132. kscan proc near
  133.  
  134.   assume DS:nothing,ES:nothing
  135.  
  136.         ; save registers.
  137.   push AX
  138.   push BX
  139.   push DI
  140.   push DS
  141.   push ES
  142.  
  143.         ; call normal service routine.
  144.   pushf                 ;(simulate interrupt)
  145.   call oldsv            ;Call original service routine.
  146.  
  147.         ; enqueue keyboard data.
  148.   call kcopy
  149.   assume DS:kbuf,ES:kbuf
  150.  
  151.         ; restore registers and return from interrupt.
  152.   pop ES
  153.   pop DS
  154.   assume DS:nothing,ES:nothing
  155.   pop DI
  156.   pop BX
  157.   pop AX
  158.   iret
  159.  
  160. kscan endp
  161.  
  162.  
  163.  
  164. ksupp proc near
  165.  
  166.   assume DS:nothing,ES:nothing
  167.  
  168.         ; save registers, set data segment.
  169.   sti                   ;Allow interrupts.
  170.   push BX
  171.   push SI
  172.   push DS
  173.   mov BX,CS             ;Set data segment.
  174.   mov DS,BX
  175.   assume DS:kbuf
  176.  
  177.         ; do function in AH.
  178.   cmp AH,0FFh           ;See if key stuff.
  179.   je kstuff             ;If so, stuff one.
  180.   test AH,AH            ;See if read.
  181.   jz kread              ;If so, wait for key data.
  182.   dec AH                ;See if status.
  183.   jz kstat              ;If so, get status.
  184.   dec AH                ;See if shift status.
  185.   jnz kdone             ;If not, just return.
  186.  
  187.         ; get shift status from original routine.
  188.   sub BX,BX             ;Get shift status in AL.
  189.   mov DS,BX
  190.   assume DS:ints
  191.   mov AL,KB_FLAG
  192.   jmp short kdone       ;Return AX.
  193.   assume DS:kbuf
  194.  
  195.         ; peek at queue for status.
  196.  kstat:
  197.   mov BX,offset kq      ;Point to queue.
  198.   cli                   ;Freeze queue.
  199.   call pkq              ;Get entry if any, set Z.
  200.   sti                   ;Set interrupts back.
  201.  
  202.         ; return, restore registers except AX, F.
  203.   pop DS
  204.   assume DS:nothing
  205.   pop SI
  206.   pop BX
  207.   retf 2                ;Discard flags on stack.
  208.   assume DS:kbuf
  209.  
  210.         ; stuff - try to stuff the scan code in DX.
  211.  kstuff:
  212.   push ES
  213.   push DI
  214.   mov ES,BX             ;Point ES to data area also.
  215.   assume ES:kbuf
  216.   mov BX,offset kq      ;Point to queue.
  217.   mov AX,DX             ;Get code to stuff.
  218.   cli                   ;Freeze queue.
  219.   call enq              ;Enqueue code.
  220.   sti                   ;Unfreeze.
  221.   mov AX,0FF00h         ;Restore AH, zero AL -> ok.
  222.   jnz ksok
  223.    inc AX               ;AL = 1 -> failure (no room to stuff).
  224.  ksok:
  225.   pop DI
  226.   pop ES
  227.   assume ES:nothing
  228.   jmp short kdone
  229.  
  230.         ; read - try to dequeue until successful.
  231.  kread:
  232.   mov BX,offset kq      ;Point to queue.
  233.   cli                   ;Freeze queue.
  234.   call deq              ;Try to get entry.
  235.   sti                   ;Allow scan interrupt.
  236.   jz kread              ;Wait until something there.
  237.  
  238.         ; return, restore registers except AX.
  239.  kdone:
  240.   pop DS
  241.   assume DS:nothing
  242.   pop SI
  243.   pop BX
  244.   iret
  245.  
  246. ksupp endp
  247.  
  248.  
  249.  
  250. kcopy proc near
  251.  
  252.  assume DS:nothing,ES:nothing
  253.  
  254.  ; kcopy - copy data from old queue to new queue.
  255.  ; Hits DS, ES, DI, BX, AX, and F.
  256.  
  257.         ; set up segments.
  258.   mov AX,CS
  259.   mov DS,AX
  260.   mov ES,AX
  261.   assume DS:kbuf,ES:kbuf
  262.  
  263.         ; lock out use of this routine.
  264.   mov AL,1              ;Try to lock out this routine.
  265.   xchg AL,ink           ;(Indivisible operation.)
  266.   test AL,AL            ;See if already locked out.
  267.   jnz nogo              ;If so, do nothing.
  268.  
  269.         ; check for data in old queue.
  270.  kloop:
  271.    mov AH,1             ;See if any data there.
  272.    pushf                ;(Simulate interrupt.)
  273.    call oldkv           ;Call original support routine.
  274.    jz kfin              ;If queue is empty, then done.
  275.    mov BX,offset kq     ;Point to keyboard queue.
  276.    test AX,AX           ;See if Ctrl Break.
  277.    jnz knbrk            ;If not, go on.
  278.  
  279.         ; empty queue on break (before enqueueing 0).
  280.     mov AX,kqsz         ;Queue size.
  281.     call mtq            ;Empty queue.
  282.     sub AX,AX           ;Restore AX.
  283.   knbrk:
  284.  
  285.         ; try to enqueue data.
  286.    cli                  ;Freeze queue.
  287.    call enq             ;Enqueue code.
  288.    sti                  ;Unfreeze.
  289.    jz kfin              ;If failure, leave the code in the old queue.
  290.    mov AH,0             ;Delete the code from the old queue.
  291.    pushf                ;(Simulate interrupt.)
  292.    call oldkv           ;Call original support routine.
  293.    jmp short kloop      ;See if there is more.
  294.  
  295.         ; finished---unlock this routine.
  296. kfin:
  297.  mov ink,0
  298.  
  299.         ; return.
  300. nogo:
  301.  ret
  302.  
  303. kcopy endp
  304.  
  305.  
  306.  
  307. mtq proc near
  308.  
  309.  assume DS:kbuf,ES:kbuf
  310.  
  311.  ; Initialize and empty queue.
  312.  ; ES:BX points to queue, AX is ring size in words.
  313.  ; F, AX, DI hit.
  314.   cld
  315.   lea DI,[BX-6]         ;Point to queue size.
  316.   shl AX,1              ;Convert size to bytes.
  317.   stosw                 ;Set size.
  318.   mov AX,BX             ;Set pointers equal.
  319.   stosw                 ;Set front.
  320.   stosw                 ;Set rear.
  321.   ret
  322.  
  323. mtq endp
  324.  
  325.  
  326.  
  327. enq proc near
  328.  
  329.  assume DS:kbuf,ES:kbuf
  330.  
  331.  ; Put entry in queue if possible.
  332.  ; DS/ES:BX points to queue, AX is value to enqueue.
  333.  ; On return Z reset indicates success, Z set failure.
  334.  ; F, DI hit.
  335.   std                   ;Set reverse direction.
  336.   mov DI,[BX-2]         ;Get rear pointer.
  337.   cmp DI,BX             ;See if pointer will underflow.
  338.   stosw                 ;Store word in queue.
  339.   ja enq1               ;If pointer not underflowed go on.
  340.    add DI,[BX-6]        ;Else, add size of queue in bytes.
  341.  enq1:
  342.   cmp DI,[BX-4]         ;See if queue full.
  343.   je enq2               ;If so, return zero set.
  344.    mov [BX-2]